program lyricdownloader;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  Classes,
  StrUtils,
  Vcl.ExtActns,
  MediaInfoDLL in 'MediaInfoDLL.pas';

const
  Version = '0.1';

type
  TFileInfo = record
    Title: string;
    Artist: string;
  end;

var
  FInpuName: string;
  FOutPutName: string;
  FTempFile: string;
  FFileInfo: TFileInfo;
  FCommandLine: string;

procedure WriteUsage();
begin
  Writeln('');
  Writeln('Usage: LyricDownloader.exe InputFile OutputFile');
  Writeln('');
end;

procedure WriteInfo();
begin
  Writeln('LyricDownloader ' + Version + ' (C) 2013 ozok ozok26@gmail.com');
  Writeln('Downloads lyric for given audio file from http://www.lyricstime.com/.');
  Writeln('This tool is a part of TAudioConverter.');
end;

function GetFileInfo: TFileInfo;
var
  MediaInfoHandle: Cardinal;
  Index: Integer;
  FTitle, FArtist: string;
begin

  // New handle for mediainfo
  MediaInfoHandle := MediaInfo_New();

  // initial values
  FTitle := '';
  FArtist := '';

  if (MediaInfoHandle <> 0) then
  begin

    try
      // read duration of file
      MediaInfo_Open(MediaInfoHandle, PWideChar(FInpuName));
      MediaInfo_Option(MediaInfoHandle, 'Complete', '1');

      FTitle := MediaInfo_Get(MediaInfoHandle, Stream_General, 0, 'Title',
        Info_Text, Info_Name);
      FArtist := MediaInfo_Get(MediaInfoHandle, Stream_General, 0, 'Artist',
        Info_Text, Info_Name);

      FTitle := Trim(FTitle);
      FArtist := Trim(FArtist);

      if (Length(FTitle) > 0) and (Length(FArtist) > 0) then
      begin
        Result.Title := LowerCase(FTitle);
        Result.Artist := LowerCase(FArtist);
      end
      else
      begin
        Writeln('Error: Cannot extract title or artist.');
      end;

    finally
      MediaInfo_Close(MediaInfoHandle);
    end;

  end;

end;

procedure SaveLyric;
const
  URL = '<url>';
var
  TmpList: TStringList;
  I: Integer;
  StartIndex: integer;
  EndIndex: integer;
  Line: string;
  Encoding: TEncoding;
  FLyricFile: TStringList;
begin

  if FileExists(FTempFile) then
  begin
    FLyricFile := TStringList.Create;
    TmpList := TStringList.Create;
    TmpList.LoadFromFile(FTempFile);
    try
      for I := 0 to TmpList.Count - 1 do
      begin
        Line := Trim(TmpList[i]);
        if Line = '<div id="songlyrics" style="padding-right:20px;">' then
        begin
          StartIndex := i;
          Break;
        end;
      end;
      for I := StartIndex to TmpList.Count - 1 do
      begin
        Line := Trim(TmpList[i]);
        if Line = '<script language="javascript" type="text/javascript">load_options();</script>'
        then
        begin
          EndIndex := i;
          Break;
        end;
      end;

      FLyricFile.Clear;
      for i := StartIndex + 1 to EndIndex - 1 do
      begin
        Line := Trim(TmpList[i]);
        Line := ReplaceText(Line, '<p>', '');
        Line := ReplaceText(Line, '</p>', '');
        Line := ReplaceText(Line, '</div>', '');
        Line := ReplaceText(Line, '<br />', '');
        if (Line <> '<br />') or (Line <> '</div>') or (Line <> '<p>') or
          (Line <> '</p>') then
        begin
          FLyricFile.Add(' ' + Line);
        end
        else
        begin
          FLyricFile.Add('');
        end;
      end;

    finally
      if FLyricFile.Count > 0 then
      begin
        FLyricFile.SaveToFile(FOutPutName);
        Writeln('Saved lyric file.');
      end
      else
      begin
        Writeln('Error: Lyric file is empty.');
      end;
      FreeAndNil(TmpList);
      FreeAndNil(FLyricFile);
      if FileExists(FTempFile) then
      begin
        DeleteFile(PChar(FTempFile));
      end;
    end;
  end
  else
  begin
    Writeln('Error: Temp file does not exit.');
  end;

end;

function ClearString(const SourceStr: string): string;
const
  Problem_Set = [',', ' ', '''', '.', ':', ';'];
var
  C: Char;
  TmpStr, TmpStr2: string;
  FoundOtherChar: Boolean;
begin

  TmpStr := SourceStr;
  FoundOtherChar := False;
  for C in TmpStr do
  begin
    if C in Problem_Set then
    begin
      TmpStr2 := TmpStr2 + '-'
    end
    else
    begin
      TmpStr2 := TmpStr2 + C
    end;
  end;
  TmpStr := LowerCase(TmpStr2);
  TmpStr2 := '';
  FoundOtherChar := False;
  for C in TmpStr do
  begin
    if FoundOtherChar then
    begin
      TmpStr2 := TmpStr2 + C;
    end
    else
    begin
      if C = '-' then
      begin
        FoundOtherChar := False;
      end
      else
      begin
        TmpStr2 := TmpStr2 + C;
        FoundOtherChar := True;
      end;
    end;
  end;
  TmpStr := LowerCase(TmpStr2);
  TmpStr2 := '';
  FoundOtherChar := False;
  TmpStr := ReverseString(TmpStr);
  FoundOtherChar := False;
  for C in TmpStr do
  begin
    if FoundOtherChar then
    begin
      TmpStr2 := TmpStr2 + C;
    end
    else
    begin
      if C = '-' then
      begin
        FoundOtherChar := False;
      end
      else
      begin
        TmpStr2 := TmpStr2 + C;
        FoundOtherChar := True;
      end;
    end;
  end;
  TmpStr := LowerCase(TmpStr2);
  Result := ReverseString(TmpStr);

end;

var
  i: integer;

begin
  WriteInfo;
  try

    if ParamCount >= 0 then
    begin

      FInpuName := ParamStr(1);
      FOutPutName := ParamStr(2);
      if FileExists(FInpuName) then
      begin
        if MediaInfoDLL_Load('MediaInfo.dll') then
        begin

          Writeln('Reading from ' + FInpuName);
          FFileInfo := GetFileInfo;
          FTempFile := ChangeFileExt(FInpuName, '.dat');
          if FileExists(FTempFile) then
          begin
            DeleteFile(PChar(FTempFile));
          end;

          Writeln('');
          Writeln('Starting to download lyric for ' + FFileInfo.Artist + '-' +
            FFileInfo.Title);
          with TDownLoadURL.Create(nil) do
          begin
            try
              URL := 'http://www.lyricstime.com/' +
                ClearString(FFileInfo.Artist) + '-' +
                ClearString(FFileInfo.Title) + '-lyrics.html';
              FileName := FTempFile;

              ExecuteTarget(nil);
            finally
              Free;
            end;
          end;
          Writeln('Done downloading.');
          SaveLyric;

        end
        else
        begin
          Writeln('Error: Cannot load mediainfo.dll.');
        end;
      end
      else
      begin
        Writeln('Error: Input file does not exist: ' + FInpuName);
      end;

    end
    else
    begin
      Writeln('Error: Wrong command count:' + FloatToStr(ParamCount));
      for I := 0 to ParamCount do
      begin
        Writeln('Parameter ' + FloatToStr(i) + ' ' + ParamStr(i));
      end;
      WriteUsage;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.
